﻿using System.Buffers.Text;
using System.Security.Cryptography;
using System.Text;

namespace WebAPI.Common.Tools
{
    public class EncryptHelper
    {
        private const int KEY_SIZE = 256;
        private const int BLOCK_SIZE = 128;
        private const string KEY_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        private const string IV_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        private static readonly string secret = "12345678aawebapi12345678aawebapi";
        private static readonly byte[] key = { 0x01, 0x02, 0x03, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };

        public static string DESCrypt(string content)
        {
            byte[] buff = Encoding.UTF8.GetBytes(content);
            Aes aes = Aes.Create();

            aes.Mode = CipherMode.CBC;
            // 注意 key 和 Iv的长度必须要是 16 的整数倍
            aes.Key = Encoding.UTF8.GetBytes(secret);
            aes.IV = key;

            string encryptedStr;

            ICryptoTransform cryptoTransform = aes.CreateEncryptor();
            using(MemoryStream ms = new MemoryStream())
            {
                using(CryptoStream stream = new CryptoStream(ms, cryptoTransform, CryptoStreamMode.Write))
                {
                    stream.Write(buff, 0, buff.Length);
                    stream.FlushFinalBlock();
                    encryptedStr = Convert.ToBase64String(ms.ToArray());
                }
            }

            return encryptedStr;
        }

        public static string DESDecrypt(string encryptStr)
        {
            byte[] encryptBuff = Convert.FromBase64String(encryptStr);
            Aes aes = Aes.Create();
            aes.Mode = CipherMode.CBC;
            aes.Key = Encoding.UTF8.GetBytes(secret);
            aes.IV = key;
            ICryptoTransform cryptoTransform = aes.CreateDecryptor();

            string rawStr;
            using (MemoryStream ms = new MemoryStream())
            {
                using(CryptoStream stream = new CryptoStream(ms, cryptoTransform, CryptoStreamMode.Write))
                {
                    stream.Write(encryptBuff, 0, encryptBuff.Length);
                    stream.FlushFinalBlock();
                    rawStr = Encoding.UTF8.GetString(ms.ToArray());
                }
            }
            return rawStr;
        }


        public static string Md5Encrypt(string content)
        {
            MD5 md5 = MD5.Create();
            byte[] buff = md5.ComputeHash(Encoding.UTF8.GetBytes(content));
            //Console.WriteLine($"length: {buff.Length}");  16 位
            StringBuilder builder = new StringBuilder();
            foreach (var item in buff)
            {
                builder.Append(item.ToString("x2"));
            }

            return builder.ToString();
        }

        public static string GenerateKey()
        {
            Random random = new Random();
            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < KEY_SIZE / 8; i++)
            {
                int index = random.Next(KEY_CHARS.Length);
                sb.Append(KEY_CHARS[index]);
            }

            return sb.ToString();
        }

        public static string GenerateIV()
        {
            Random random = new Random();
            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < BLOCK_SIZE / 8; i++)
            {
                int index = random.Next(IV_CHARS.Length);
                sb.Append(IV_CHARS[index]);
            }

            return sb.ToString();
        }

        public static void CreatePrPubKey(out string pubKey,out string priKey)
        {
            RSA rsa = new RSACryptoServiceProvider();
            pubKey = Convert.ToBase64String(rsa.ExportRSAPublicKey());
            priKey = Convert.ToBase64String(rsa.ExportRSAPrivateKey());
        }

        public static byte[] RSAEncrypt(string content, string encryptKey)
        {
            using (RSA rsa = new RSACryptoServiceProvider())
            {
                rsa.ImportRSAPublicKey(Convert.FromBase64String(encryptKey), out _);
                return rsa.Encrypt(Encoding.UTF8.GetBytes(content), RSAEncryptionPadding.Pkcs1);
            }
        }

        public static byte[] RSADecrypt(byte[] data, string decryptKey)
        {
            using (RSA rsa = RSA.Create())
            {
                rsa.ImportRSAPrivateKey(Convert.FromBase64String(decryptKey), out _);
                return rsa.Decrypt(data, RSAEncryptionPadding.Pkcs1);
            }
        }
    }
}